Список L
содержит n целых чисел. Найдите сумму
чисел на отрезке между индексами i и j включительно, то есть
RSQ(i, j)
= L[i] + L[i + 1] + L[i + 2] + ... +
L[j]
Вход. Первая строка содержит количество тестов t (1 ≤ t ≤ 5). Каждый тест начинается с пустой строки, за которой следует
строка с двумя целыми числами n и q (1 ≤ n, q ≤ 105).
Следующая строка содержит n
неотрицательных целых чисел, каждое из которых не больше 109. Затем
следуют q строк, каждая из которых
содержит два целых числа i и j (0 ≤ i, j < n).
Выход. Для каждого
запроса выведите в отдельной строке значение RSQ(i, j). Ответы для разных тестов
разделяйте пустой строкой.
| Пример
  входа | Пример
  выхода | 
| 2 10 8 1 2 3 4 5 6
  7 8 9 10 4 4 3 8 0 3 1 3 2 9 8 9 6 8 5 7 10 5 10 9 7 20 14
  23 14 27 38 77 3 6 7 9 6 7 1 5 4 8 | 5 39 10 9 52 19 24 21 71 142 41 73 116 | 
последовательности,
частичные суммы
Анализ алгоритма
По входному
списку чисел L1, …, Ln
построим массив частичных сумм 
s1 = L1,
s2 = L1 + L2,
…
sn = L1 + L2 + … + +
Ln
Тогда 
RSQ(i, j)
= L[i] + L[i + 1] + L[i + 2] + ... +
L[j] = sj – si-1
Реализация
алгоритма
Частичные суммы
будем вычислять “на лету” при чтении входного списка чисел L и сохранять их в массиве s.
#define MAX 100010
long long
s[MAX];
Читаем входные данные.
scanf("%d",&tests);
while(tests--)
{
  scanf("%d
%d",&n,&q);
  scanf("%lld",&s[1]);
Заполним массив частичных сумм s.
  for(i = 2; i
<= n; i++)
  {
    scanf("%lld",&s[i]);
    s[i] += s[i-1];
  }
Последовательно обрабатываем q запросов. Поскольку индексы a и b в запросах RSQ(a, b) начинаются с нуля, а массив частичных сумм s
строится с индекса 1, то для каждого запроса ответ находим слудующим образом:
RSQ(a, b) = sb+1
– sa.
  for(i = 0; i
< q; i++)
  {
    scanf("%d
%d",&a,&b);
    printf("%lld\n",s[b+1]
- s[a]);
  }
Ответы для соседних тестов разделяются
пустой строкой.
  if (tests
> 0) printf("\n");
}
Реализация алгоритма – алгоритм МО
#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int tests, n, q, a, b, i, block, curL, curR, l, r;
vector<long long> s, ans;
long long sum;
struct queries
{
  int l, r, idx;
};
vector<queries> query;
int f(queries a, queries b)
{
  if ((a.l / block) == (b.l / block))
    //return
a.r < b.r;
    return (a.l / block % 2 == 0) ? a.r < b.r : a.r > b.r;
  return a.l < b.l;
}
int main(void)
{
  scanf("%d",
&tests);
  while (tests--)
  {
    scanf("%d %d", &n,
&q);
    s.clear(); s.resize(n);
    for (i = 0; i < n; i++)
      scanf("%lld", &s[i]);
    query.clear(); query.resize(q);
    for (i = 0; i < q; i++)
    {
      scanf("%d %d",
&query[i].l, &query[i].r);
      query[i].idx = i;
    }
    block = sqrt(n);
    sort(query.begin(), query.end(), f);
    curL = 0; 
curR = -1; sum = 0;
    ans.clear(); ans.resize(q);
    for (i = 0; i < query.size(); i++)
    {
      l = query[i].l;
      r = query[i].r;
      while (curL < l)
      {
       
sum -= s[curL];
        curL++;
      }
      while (curL > l)
      {
       
curL--;
        sum += s[curL];
      }
      while (curR < r)
      {
        curR++;
        sum += s[curR];
      }
      while (curR > r)
      {
        sum -= s[curR];
        curR--;
      }
      ans[query[i].idx] = sum;
    }
    for (i = 0; i < ans.size(); i++)
      printf("%lld\n", ans[i]);
    printf("\n");
  }
  return 0;
}